24-7 PBz

若要使用 WSH 來直接抓取網頁,可以使用 Visual Basic 6 的元件 InetCtls.Inet,如果你的機器尚未安裝此元件,可以依照下列方式來進行安裝:
  1. 從下列網址下載壓縮檔案 msinet.cab:
    http://activex.microsoft.com/controls/vb6/msinet.cab
    (近端備份:...\wsh\download\msinet.cab
  2. 對 msinet.cab 進行解壓縮,得到 MSINET.INF 和 MSINET.OCX,將這兩個檔案放到 c:\windows\system32 目錄下。
  3. 開啟 DOS 視窗,進入 c:\windows\system32 目錄,執行「regsvr32 msinet.ocx」,即可完成安裝。
安裝完成後,我們就可以使用 WSH 來直接抓取網頁,請見下列範例:

原始檔(getWebPage01.js):(灰色區域按兩下即可拷貝)
// 抓取一個網頁
inet=new ActiveXObject("InetCtls.Inet");		// 取得 Inet Control 物件
inet.Url="http://www.cs.nthu.edu.tw";			// 欲下載之網頁
inet.RequestTimeOut=60;					// 設定嘗試時間
WScript.Echo("Downloading \""+inet.Url+"\"...");
content = inet.OpenURL();				// 下載網頁
WScript.Echo(content);					// 顯示網頁內容

使用通用運算式,我們可以在抓取網頁後,顯示此網頁的標題,例如:

原始檔(getWebPage02.js):(灰色區域按兩下即可拷貝)
// 抓取一個網頁,並抓出其標題
inet=new ActiveXObject("InetCtls.Inet");		// 取得 Inet Control 物件
inet.Url="http://www.cs.nthu.edu.tw";			// 欲下載之網頁
inet.RequestTimeOut=60;					// 設定嘗試時間
WScript.Echo("Downloading \""+inet.Url+"\"...");
content = inet.OpenURL();				// 下載網頁
pattern = /<title>(.*)<\/title>/i;			// 定義通用表示式
title = pattern.exec(content);				// 抓出標題
WScript.Echo("位於「"+inet.Url+"」的網頁的標題是「"+RegExp.$1+"」!");	// 顯示結果

我們也可以在抓取一個網頁後,立即將網頁儲存到硬碟中的某個檔案:

原始檔(getWebPage03.js):(灰色區域按兩下即可拷貝)
// 抓取一個網頁,並將其內容存入一個檔案
inet=new ActiveXObject("InetCtls.Inet");		// 取得 Inet Control 物件
inet.Url="http://www.cs.nthu.edu.tw";			// 欲下載之網頁
inet.RequestTimeOut=20;					// 設定嘗試時間
WScript.Echo("Downloading \""+inet.Url+"\"...");
content = inet.OpenURL();				// 下載網頁
// 以下將網頁內容寫入本機檔案
fso = new ActiveXObject("Scripting.FileSystemObject");
forReading=1, forWriting=2;
fileName="test.htm";
fid=fso.OpenTextFile(fileName, forWriting, true);
fid.Write(content);
fid.Close();
WScript.Echo("從「"+inet.Url+"」抓到的內容已被存入「"+fileName+"」!");

我們也可以在抓取網頁後,利用通用表示法來抓出網頁中的連結網址和相關文字(Ancher Texts):

原始檔(getWebPage04.js):(灰色區域按兩下即可拷貝)
// 抓取一個網頁,並抽取出網頁內容的所有連結(功能並不完全,可再改進!)
inet=new ActiveXObject("InetCtls.Inet");		// 取得 Inet Control 物件
inet.Url="http://www.cs.nthu.edu.tw";			// 欲下載之網頁
inet.RequestTimeOut=20;					// 設定嘗試時間
WScript.Echo("Downloading \""+inet.Url+"\"...");
content = inet.OpenURL();				// 下載網頁
pattern=/<A(.*?)<\/A>/gi;				// 定義通用表示式
found=content.match(pattern);				// 抓出連結
pattern2=/<\s*A\s+HREF\s*=\s*"?(.*?)"?\s*>(.*?)<\s*\/\s*A\s*>/i;	// 另一個通用運算式
for (i=0; i<found.length; i++){
	pattern2.exec(found[i]);		// 抓出連結的網址以及連結的文字
	WScript.Echo(found[i]+" ===> URL="+RegExp.$1+", TEXT="+RegExp.$2);
}

在上述範例中,我們利用 WSH 來抓取清大資訊系的首頁,並使用通用表示法來抓取連結網址及連結文字,典型輸出如下:

Downloading "http://www.cs.nthu.edu.tw"... <a href="2003NTHU_CS_Chinese.doc" target="_blank">(中)</a> ===> URL=2003NTHU_CS_Chinese.doc" target="_blank, TEXT=(中) <a href="2003NTHU_CS_English.doc" target="_blank">(英)</a> ===> URL=2003NTHU_CS_English.doc" target="_blank, TEXT=(英) <a href="/intro.html"><img src="/icon/csbuild_8.jpg" lowsrc="/icon/csbuild_7b.jpg" border=0 alt="清華資訊簡史"></a> ===> URL=/intro.html, TEXT=<img src="/icon/csbuild_8.jpg" lowsrc="/icon/csbuild_7b.jpg" border=0 alt="清華資訊簡史"> <a href="Grading_report.doc">系所自我評鑑報告</a> ===> URL=Grading_report.doc, TEXT=系所自我評鑑報告 <a href="mailto:www@cs.nthu.edu.tw">意 見 與 指 教</a> ===> URL=mailto:www@cs.nthu.edu.tw, TEXT=意 見 與 指 教 <a href="/webteam">製 作 小 組</a> ===> URL=/webteam, TEXT=製 作 小 組 <a href="special.html"><font face="Arials">學 術 卓 越 & 社 區 關 懷</a> ===> URL=special.html, TEXT=<font face="Arials">學 術 卓 越 & 社 區 關 懷 ... 前面範例所用的 InetCtls.Inet 元件,比較簡單,所以無法偵測網路斷線的情況,另一個 IIS 內建的元件 WinHttp.WinHttpRequest,則可以有較多偵錯功能,以下範例可以抓取 Google 首頁:

原始檔(getWebPage05.js):(灰色區域按兩下即可拷貝)
// 抓取一個網頁並顯示其內容
url="http://www.google.com";
try {
	WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
	WinHttpReq.Open("GET", url, false);
	WinHttpReq.Send();
	result = WinHttpReq.ResponseText;
} catch (objError) {
	result = objError+"\n";
	result += ("objError.number = "+(objError.number & 0xFFFF).toString()+"\n");
	result += ("objError.description = "+objError.description);
}
WScript.Echo(result);

讀者可以暫停網路,再試看看上述範例,就會印出抓不到網頁的錯誤訊息了。

你也可以使用另一個內建元件 XMLHTTP 來抓取網頁:

原始檔(getUrl.js):(灰色區域按兩下即可拷貝)
url = "http://www.google.com.tw";
objHttp = new ActiveXObject("Microsoft.XMLHTTP");
objHttp.open("GET", url, false, "");
objHttp.send();
content = objHttp.responseText;
WScript.Echo(content);

我們也可以抓取諸如 jpg 或 mid 等二進制檔案:

原始檔(getBinaryFile.js):(灰色區域按兩下即可拷貝)
// Get Binary File from Web
// Usage: cscript getBinaryFile.js url output
// Example: cscript getBinaryFile.js http://neural.cs.nthu.edu.tw/jang/books/javascript/example/image/19980425/0041.jpg annie.jpg
// Roger Jang, 20081215, tested under Vista

args = WScript.Arguments;
if (args.Count()!=2) {
	WScript.Echo("Usage: cscript " + WScript.ScriptName + " url output");
	WScript.Echo("For example:");
	WScript.Echo("\tcscript " + WScript.ScriptName + " \"http://neural.cs.nthu.edu.tw/jang/books/javascript/example/image/19980425/0041.jpg\" \"annie.jpg\"");
	WScript.Quit();
}

url = args(0);
output = args(1);
getBinaryFile(url, output);

function getBinaryFile(url, output){

		// ====== 使用 Microsoft.XMLHTTP 抓取檔案。
		http = WScript.CreateObject("Msxml2.ServerXMLHTTP.3.0");
		http.open("GET", url, false);
		WScript.Echo("Retrieving file at " + url);
		http.send();
		statusCode = http.status;
		if (statusCode != 200){			// 檔案不正常
			WScript.Echo("Error in retrieving file at " + url);
			WScript.Echo("Status code = " + statusCode);
			WScript.Quit();
		}
		file = http.responseBody;
		BinaryStream = WScript.CreateObject("ADODB.Stream");
		BinaryStream.type = 1;
		BinaryStream.open();
		// ====== 儲存檔案
		WScript.Echo("Saving file to " + output + "...");
		BinaryStream.write(file);
		BinaryStream.saveToFile(output, 2);
		WScript.Echo("Done.");
}


JScript 程式設計與應用:用於單機的 WSH 環境